package com.derbysoft.synxisadapter.dswitch2.service.impl;

import com.derbysoft.remote.dswitch.core.GenericRQ;
import com.derbysoft.remote.dswitch.core.GenericRS;
import com.derbysoft.remote.dswitch.core.ResponseHeader;
import com.derbysoft.remote.dswitch.core.SuccessDTO;
import com.derbysoft.synxisadapter.commons.dto.synxis.OtaRequestMessage;
import com.derbysoft.synxisadapter.commons.dto.synxis.OtaResponseMessage;
import com.derbysoft.synxisadapter.commons.exception.ChannelNotFoundException;
import com.derbysoft.synxisadapter.commons.model.Channel;
import com.derbysoft.synxisadapter.commons.repository.ChannelRepository;
import com.derbysoft.synxisadapter.dswitch2.service.HotelProviderService;
import com.derbysoft.synxisadapter.dswitch2.service.ProviderWebService;
import com.derbysoft.synxisadapter.dswitch2.translator.Translator;

import java.util.ArrayList;
import java.util.List;

public abstract class AbstractHotelService<RQ extends GenericRQ, RS extends GenericRS, PRQ extends OtaRequestMessage, PRS extends OtaResponseMessage> implements HotelProviderService<RQ, RS> {

    protected Translator<RQ, List<PRQ>, Void> requestTranslator;
    protected Translator<List<PRS>, RS, RQ> responseTranslator;
    protected ProviderWebService providerWebService;
    protected ChannelRepository channelRepository;

    @Override
    public RS invoke(RQ rq) {
        Channel channel = loadChannel(rq);
        List<PRQ> requestList = requestTranslator.translate(rq, null);

        List<PRS> responseList = new ArrayList<PRS>();

        for (PRQ request : requestList) {
            PRS response = (PRS) providerWebService.invoke(request, channel);
            if (hasError(response)) {
                throw new IllegalStateException(response.getErrors().getError().get(0).getShortText());
            }
            responseList.add(response);
        }

        RS rs = responseTranslator.translate(responseList, rq);

        rs.setSuccess(new SuccessDTO());
        rs.setHeader(createHeader(rq));

        return rs;
    }

    protected Channel loadChannel(RQ rq) {
        Channel channel = channelRepository.findByPassport(rq.getHeader().getSource().getUniqueID().getId());
        if (channel == null) {
            throw new ChannelNotFoundException(rq.getHeader().getSource().getUniqueID().getId());
        }
        return channel;
    }

    protected boolean hasError(PRS providerResponse) {
        return providerResponse.getSuccess() == null;
    }

    protected ResponseHeader createHeader(RQ rq) {
        ResponseHeader responseHeader = new ResponseHeader();
        responseHeader.setTaskId(rq.getHeader().getTaskId());
        return responseHeader;
    }

    public void setProviderWebService(ProviderWebService lowCostWebService) {
        this.providerWebService = lowCostWebService;
    }

    public void setRequestTranslator(Translator<RQ, List<PRQ>, Void> requestTranslator) {
        this.requestTranslator = requestTranslator;
    }

    public void setChannelRepository(ChannelRepository channelRepository) {
        this.channelRepository = channelRepository;
    }

    public void setResponseTranslator(Translator<List<PRS>, RS, RQ> responseTranslator) {
        this.responseTranslator = responseTranslator;
    }
}
